package com.stxx.stiot2.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.stxx.framwork.domain.model.Option;
import com.stxx.framwork.domain.model.PageQuery;
import com.stxx.framwork.domain.model.PageResult;
import com.stxx.framwork.exception.ServiceException;
import com.stxx.framwork.tran.TranUtils;
import com.stxx.framwork.utils.StoreUtils;
import com.stxx.stiot2.constants.SystemConstants;
import com.stxx.stiot2.domain.Device;
import com.stxx.stiot2.domain.Profile;
import com.stxx.stiot2.domain.Terminal;
import com.stxx.stiot2.domain.ext.DeviceSignal;
import com.stxx.stiot2.domain.ext.SignalEx;
import com.stxx.stiot2.service.DeviceService;
import com.stxx.stiot2.service.ProfileService;
import com.stxx.stiot2.service.TerminalService;
import com.stxx.stiot2.service.tran.AssetTypeTranService;
import lombok.SneakyThrows;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.data.annotation.Transaction;
import org.noear.solon.data.sql.SqlBuilder;

import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Fuzhenlei
 * @date 2025/01/15 16:41
 */
@Component
public class DeviceServiceImpl implements DeviceService{
    @Inject
    StoreUtils storeUtils;
    @Inject
    TerminalService terminalService;
    @Inject
    ProfileService profileService;
    @Inject
    AssetTypeTranService assetTypeTranService;

    @Override
    public Device queryById(Long id) {
        try {
            Device device = storeUtils.selectById(id,Device.class);
            TranUtils.build().add("assetTypeId",assetTypeTranService).tran(device);
            additional(device);
            return device;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public int insert(Device bean) throws SQLException {
        validEntityBeforeSave(bean);
        int r = storeUtils.insert(bean);
        terminalService.association(bean.getDeviceId(),getTerminals(bean));
        return r;
    }

    @Transaction
    @Override
    public int update(Device bean) throws SQLException {
        validEntityBeforeSave(bean);
        int r = storeUtils.update(bean);
        terminalService.association(bean.getDeviceId(),getTerminals(bean));
        return r;
    }

    private List<String> getTerminals(Device bean){
        return bean.getTerminalList().stream().map(Terminal::getCode).collect(Collectors.toList());
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(Device bean) throws SQLException {
        if(bean.getDeviceId()!=null){
            throw new ServiceException("编号不能为空");
        }
    }



    @Override
    public int delete(Long id) throws SQLException {
        return storeUtils.delete(Device.class,id);
    }

    @Override
    public int deleteByIds(Long[] ids) throws SQLException {
        return storeUtils.deleteByIds(Device.class, ids);
    }

    @Override
    public List<Device> list(Device obj) throws SQLException {
        List<Device> list= storeUtils.selectList(Device.class,obj);
        TranUtils.build().add("assetTypeId",assetTypeTranService).tran(list);
        additional(list);
        return list;
    }

    @Override
    public PageResult<Device> pageList(Device obj, PageQuery pageQuery) throws SQLException {
        PageResult<Device> r = storeUtils.selectPageList(Device.class,obj,pageQuery);
        TranUtils.build().add("assetTypeId",assetTypeTranService).tran(r.getData());
        additional(r.getData());
        return r;
    }
    @Override
    public List<DeviceSignal> getSignals(Long deviceId) throws SQLException {
        List<Terminal> list = terminalService.queryByDeviceId(deviceId);
        if(list==null||list.size()==0){return new ArrayList<>();}
        List<DeviceSignal> signals = new ArrayList<>();
        for(Terminal terminal : list){
            Map<String,SignalEx> signalExes = profileService.signals(terminal.getProfileCode());
            signalExes.forEach((k,v)->{
                DeviceSignal deviceSignal = BeanUtil.toBean(v,DeviceSignal.class);
                deviceSignal.setTerminalCode(terminal.getCode());
                deviceSignal.setTerminalName(terminal.getName());
                signals.add(deviceSignal);
            });
        }
        return signals;
    }

    private void additional(List<Device> list) throws SQLException {
        for(Device device : list){
            additional(device);
        }
    }
    private void additional(Device bean) throws SQLException {
        List<Terminal> list = terminalService.queryByDeviceId(bean.getDeviceId());
        bean.setTerminalList(list);
    }

    @Override
    public List<Option> queryOptions(String id, String w, String pid) throws SQLException {
        SqlBuilder sb = new SqlBuilder();
        sb.append("select device_id as value,name as label from "+storeUtils.getTableName(Device.class));
        if(id != null){
            sb.append(" where device_id=?",id);
        }else{
            sb.append(" where (device_id like concat('%',?,'%') or name like concat('%',?,'%'))",w,w);
        }
        sb.append(" limit "+ SystemConstants.options_query_max_size);
        return storeUtils.sql(sb).queryRowList(Option.class);
    }

    @Override
    public List<Option> queryOptions(String[] ids) throws SQLException {
        SqlBuilder sb = new SqlBuilder();
        sb.append("select device_id as value,name as label from "+storeUtils.getTableName(Device.class)+" where device_id in (");
        sb.append(StrUtil.repeat("?,",ids.length));
        sb.removeLast();
        sb.append(")",ids);
        return storeUtils.sql(sb).queryRowList(Option.class);
    }
}
